/**
 * 
 */
package com.py.credit.controller;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.py.credit.common.rest.RestServiceResult;
import com.py.credit.entity.BatchLog;
import com.py.credit.entity.Column;
import com.py.credit.entity.Table;
import com.py.credit.service.BatchLogService;
import com.py.credit.service.ColumnService;
import com.py.credit.service.CreditConcernedService;
import com.py.credit.service.DataRelateService;
import com.py.credit.service.TableService;
import com.py.credit.utils.DateUtil;
import com.py.credit.utils.UuidUtil;

/**
 * 自动关联
 * 
 * @author dd
 *
 */
@RestController
@RequestMapping("/associationPerform")
public class AssociationPerformController {

	private static final Logger LOG = Logger.getLogger(AssociationPerformController.class);

	@Autowired
	private BatchLogService batchLogService;

	@Autowired
	private DataRelateService dataRelateService;

	@Autowired
	private ColumnService columnService;

	@Autowired
	private TableService tableService;
	@Autowired
	private CreditConcernedService creditConcernedService;

	private static final int BATCH_COUNT = 1000;

	@RequestMapping("/association1.do")
	public RestServiceResult<String> Associate() {

		int waitCount = 0;

		// 未做关联的所有批次
		List<BatchLog> unAssociatedBatchLogs = batchLogService.getUnAssociatedBatch();
		// 取其中一个进行关联操作
		if (!CollectionUtils.isEmpty(unAssociatedBatchLogs)) {
			BatchLog batchLog = unAssociatedBatchLogs.get(0);
			batchLogService.updateBatchLogAssociationStatus(batchLog.getId(), "P");
			int tableId = batchLog.getTarget();
			Table table = tableService.getTableById(tableId);
			String tableName = "t_" + table.getResourceId();
			String batchId = batchLog.getId();

			int datasourceId = batchLog.getDatasourceId();
			// 获取自动关联指标
			List<String> associationMetricCodes = dataRelateService.getAssociationMetricCodesByDbId(datasourceId);
			// 获取公共指标
			List<String> commonMetricCodes = dataRelateService.getCommonMetricCodesByDbId(datasourceId);
			List<Column> tableColumns = columnService.getListByTableId(tableId);
			// 判断 表里是否包含用来关联的字段,没有跳过该表的关联操作
			boolean exist = dataRelateService.existAssociationMetricCodes(tableColumns, associationMetricCodes);

			if (exist) {

				boolean isEnd = false;

				while (!isEnd) {

					List<Map<String, Object>> recordList = null;

					try {

						// 分次查出某一批次数据
						recordList = dataRelateService.getRecordsByTableName(tableName, batchId, commonMetricCodes,
								BATCH_COUNT);

					} catch (Exception e) {

						LOG.error("表【" + tableName + "】查询出错," + "主要指标:" + commonMetricCodes, e);

						// 错一次整个表就不需要查了,都是出错的
						break;

					}

					if (!CollectionUtils.isEmpty(recordList)) {
						// 关联指标的值是null或空值则无法关联
						for (Map<String, Object> record : recordList) {

							boolean skip = false;

							for (String associatecode : associationMetricCodes) {

								Object object = record.get(associatecode);

								if (object == null || StringUtils.isBlank(object.toString())) {

									skip = true;

									break;

								}

							}

							if (skip) {

								try {
									// 更新记录表中的状态 为暂时无法关联 status = T
									dataRelateService.unableAuth((Integer) record.get("recordId"), tableName);

									// 加入record表(暂时无法关联的数据)
									dataRelateService.addZooRecord(record, tableId, commonMetricCodes, datasourceId,
											batchLog.getDeptId());

								} catch (Exception e) {

									LOG.error("关联字表空缺,暂时无法关时插入record表出错:表名【" + tableName + "】,数据:【" + record + "】", e);

								}

								waitCount++;

								continue;

							}

							// 遍历数据用自动关联指标匹配unique中的数据

							Map<String, String> uniqueValue = null;

							try {

								// 用自动关联指标匹配unique表中的唯一记录

								uniqueValue = dataRelateService.getMatchZooUnique(datasourceId, associationMetricCodes,
										record);

							} catch (Exception e) {

								// 如果匹配了多条,做无法关联操作
								// 更新记录表中的状态 为暂时无法关联 status = T

								LOG.error("数据====>【" + record + "】与unique表中匹配出错", e);

								try {
									dataRelateService.unableAuth((Integer) record.get("recordId"), tableName);
									// 加入record表(暂时无法关联的数据)
									dataRelateService.addZooRecord(record, tableId, commonMetricCodes, datasourceId,
											batchLog.getDeptId());

								} catch (Exception e1) {

									LOG.error(
											"unique表存在重复数据时做无法关联,插入record表出错:表名【" + tableName + "】,数据:【" + record + "】",
											e1);

								}

								waitCount++;

								continue;

							}

							// 成功匹配unique表中的唯一记录

							if (uniqueValue != null) {

								Map<String, String> fillBackData = new HashMap<String, String>();

								String tybm = uniqueValue.get("TYBM");

								if (dataRelateService.needAssociation(record, uniqueValue, commonMetricCodes,
										fillBackData)) {

									boolean associateSuccess = false;
									// 补填unique表
									if (fillBackData.size() > 0) {

										try {

											dataRelateService.updateZooUnique(datasourceId, tybm, fillBackData);

											// 更新 数据表中的数据状态为 A已关联
											dataRelateService.updateRecord(tableName, (Integer) record.get("recordId"),
													tybm);

											associateSuccess = true;

										} catch (Exception e) {

											// 更新记录表中的状态 为暂时无法关联 status = T
											// 但不加入record，字段过长也会导致失败
											dataRelateService.unableAuth((Integer) record.get("recordId"), tableName);

											LOG.error("回填时更新unique失败,更新记录表中的状态 为T但不加入record,表名【" + tableName + "】,数据:【"
													+ record + "】", e);

										}
									} else {

										// 更新 数据表中的数据状态为 A已关联
										dataRelateService.updateRecord(tableName, (Integer) record.get("recordId"),
												tybm);
										associateSuccess = true;

									}

									if (associateSuccess) {

										// 如果是法人库新增关注企业数据

										try {

											if (100000 == datasourceId) {

												String modifyTime = DateUtil.getInstance().dateToStr(new Date(),
														DateUtil.YYYY_MM_DD);

												String qymc = uniqueValue.get(associationMetricCodes.get(0));

												Integer id = dataRelateService.getConcernedSubjectId(qymc);

												if (id != null) {

													creditConcernedService.addNewRecord(id,
															(Integer) record.get("recordId"), table.getResourceId());
													creditConcernedService.updateCheckStatus("N", id, modifyTime);

												}

											}

											// 先查询t_dc_tybm_cube是否存在相同的tybm和表名,避免同一张表里的数据相关联而产生冗余数据
											if (!dataRelateService.exist(table.getResourceId(), tybm)) {
												// 录 t_dc_tybm_cube
												dataRelateService.addTybmCube(table.getResourceId(), tybm);
											}

										} catch (Exception e) {

											LOG.error("信用关注添加出错", e);

										}
									}

								} else {

									try {

										// 更新记录表中的状态 为暂时无法关联 status = T
										dataRelateService.unableAuth((Integer) record.get("recordId"), tableName);
										// 加入record表(暂时无法关联的数据)
										dataRelateService.addZooRecord(record, tableId, commonMetricCodes, datasourceId,
												batchLog.getDeptId());

									} catch (Exception e) {

										LOG.error("needAssociation 不符合后,暂时无法关联插入record表出错:表名【" + tableName + "】,数据:【"
												+ record + "】", e);

									}

									waitCount++;
								}

							} else {

								// 不匹配unique的记录

								// 数据按主要关联指标中任意一个字段(空值("",null)不算)是否存在于unique记录中

								List<String> majorMetricCodes = dataRelateService
										.getMajorMetricCodesByDbId(datasourceId);

								boolean match = dataRelateService.majorMatchZooUniques(datasourceId, majorMetricCodes,
										record);
								// 如果不存在,插入unique

								if (!match) {

									String tybm = UuidUtil.getInstance().getUUid();

									try {
										// 插入unique
										dataRelateService.addZooUnique(tybm, record, datasourceId, commonMetricCodes);
										// 更新 数据表中的数据状态为 A已关联
										dataRelateService.updateRecord(tableName, (Integer) record.get("recordId"),
												tybm);

										// 先查询t_dc_tybm_cube是否存在相同的tybm和表名
										if (!dataRelateService.exist(table.getResourceId(), tybm)) {
											// 录 t_dc_tybm_cube
											dataRelateService.addTybmCube(table.getResourceId(), tybm);
										}

									} catch (Exception e) {

										// 更新 数据表中的数据状态为 T但不加入record应为是错误数据
										dataRelateService.unableAuth((Integer) record.get("recordId"), tableName);

										LOG.error("插入unique出错,数据表中的数据状态为 T但不加入record表:表名【" + tableName + "】,数据:【"
												+ record + "】", e);

									}

								} else {

									// 如果存在,则加入record表,更新数据状态为暂时无法关联

									// 更新记录表中的状态 为暂时无法关联 status = T

									try {

										dataRelateService.unableAuth((Integer) record.get("recordId"), tableName);
										// 加入record表(暂时无法关联的数据)
										dataRelateService.addZooRecord(record, tableId, commonMetricCodes, datasourceId,
												batchLog.getDeptId());

									} catch (Exception e) {

										LOG.error("unique存在记录时,暂时无法关联插入record表出错:表名【" + tableName + "】,数据:【" + record
												+ "】", e);

									}

									waitCount++;

								}

							}

						}

					} else {

						isEnd = true;
					}

				}

			} else {

				LOG.error("数据表 【" + tableName + "】不包含关联字段: " + associationMetricCodes.get(0) + ",跳过该表的关联,批次:【" + batchId
						+ "】");
			}

			batchLogService.updateBatchLogAssociationStatus(batchLog.getId(), "S");

			batchLogService.updateBatchLogWaitCount(batchId, waitCount);

		}
		return new RestServiceResult<String>();

	}

}
